#include <iostream>
#include <algorithm>
using namespace std;


#define ADD 1
#define SUB 2
#define MUL 3
#define DIV 4
#define EXP 5
#define SEND 6
#define RECIEVE 7

//内部飞地定义
class subEnclave {
	private:
		int subEnlaveID;
		int tag;
		double result;
		double rev;
	public:
		subEnclave();
		int setID(int);
		int setTag(int);
		double add(double, double);
		double sub(double, double);
		double mul(double, double);
		double div(double, double);
		double exp(double);
		int get_tag();
		int get_id();
		friend int send(subEnclave &, subEnclave &);
		friend int recieve(subEnclave &, subEnclave &);
		~subEnclave();
};

subEnclave::subEnclave() {
	subEnlaveID = 0;
	tag = 0;
	result = 0;
	rev = 0;
	cout << "create subenclave success" << endl;
}

int subEnclave::setID(int ID) {

	this->subEnlaveID = ID;
	return 0;
}

int subEnclave::setTag(int tag) {
	this->tag = tag;
	return 0;
}

double subEnclave::add(double a = 20, double b = 10) {
	result = a + b;
	return result;
}

double subEnclave::sub(double a = 20, double b = 10) {
	result = a - b;
	return result;
}

double subEnclave::mul(double a = 20, double b = 10) {
	result = a * b;
	return result;
}

double subEnclave::div(double a = 20, double b = 10) {
	result = a / b;
	return result;
}

double subEnclave::exp(double x = 7) {
	result = x * x + 2 * x + 1;
	return result;
}

int subEnclave::get_tag() {
	return tag;
}

int subEnclave::get_id() {
	return subEnlaveID;
}

int send(subEnclave &a, subEnclave &b) {
	b.rev = a.result;
	return 0;
}

int recieve(subEnclave &a, subEnclave &b) {
	a.rev = b.result;
	return 0;
}

subEnclave::~subEnclave() {
	cout << "destroy subenclave success" << endl;
}

bool Check_duplicates(int *arr, int num);
int compute(int tag, subEnclave *arr, int size, int sub);
int Set_subEnclaveID(subEnclave *arr, int size);
int Use_subEnclave(subEnclave *arr, int size);

//判断重复ID
bool Check_duplicates(int *arr, int num) {
	sort(arr, arr + num);
	for (int i = 0; i < num - 1; i++) {
		if (arr[i] == arr[i + 1])
			return true;
	}
	return false;
}

//飞地内计算
int compute(int tag, subEnclave *arr, int size, int sub) {
	int ID;
	int sub1;
	arr[sub].setTag(tag);
	if (tag == ADD) {
		cout << "result:" << arr[sub].add() << endl;
	} else if (tag == SUB) {
		cout << "result:" << arr[sub].sub() << endl;
	} else if (tag == MUL) {
		cout << "result:" << arr[sub].mul() << endl;
	} else if (tag == DIV) {
		cout << "result:" << arr[sub].div() << endl;
	} else if (tag == EXP) {
		cout << "result:" << arr[sub].exp() << endl;
	} else if (tag == SEND) {
		cout << "Please enter the subEnclaveID of the recipient:";
		while (1) {
			sub1 = -1;
			cin >> ID;
			for (int i = 0; i < size; i++) {
				if (ID == arr[i].get_id()) {
					sub1 = i;
					break;
				}
			}
			if (sub1 == -1) {
				cout << "The subEnclaveID was not found,please re-enter:";
				continue;
			} else
				break;
		}
		send(arr[sub], arr[sub1]);
		cout << "Send Success!" << endl;
	} else if (tag == RECIEVE) {
		cout << "Please enter the subEnclaveID of the Sender:";
		while (1) {
			sub1 = -1;
			cin >> ID;
			for (int i = 0; i < size; i++) {
				if (ID == arr[i].get_id()) {
					sub1 = i;
					break;
				}
			}
			if (sub1 == -1) {
				cout << "The subEnclaveID was not found,please re-enter:";
				continue;
			} else
				break;
		}
		recieve(arr[sub], arr[sub1]);
		cout << "Recieve Success!" << endl;
	} else {
		cout << "error" << endl;
	}
	return 0;
}

//设置内部飞地ID
int Set_subEnclaveID(subEnclave *arr, int size) {
	int ID;
	int check_id[size];
	while (1) {
		cout << "Please enter the subEnclaveID in turn:" << endl;
		for (int i = 0; i < size; i++) {
			cin >> ID;
			check_id[i] = ID;
		}
		if (Check_duplicates(check_id, size) == true) {
			cout << "Duplicate IDs were found,please re-enter!" << endl << endl;
			continue;
		} else
			break;
	}
	for (int i = 0; i < size; i++) {
		arr[i].setID(check_id[i]);
	}
	return 0;
}

//使用内部飞地
int Use_subEnclave(subEnclave *arr, int size) {
	int sub, ID, op;
	while (1) {
		sub = -1;
		cout << "Please enter the subEnclaveID you want to operate: ";
		cin >> ID;
		for (int i = 0; i < size; i++) {
			if (ID == arr[i].get_id()) {
				sub = i;
				break;
			}
		}
		if (sub == -1) {
			cout << "The subEnclaveID was not found,please re-enter!" << endl;
			continue;
		}

		cout << "Please enter the function you want:" << endl;
		cout << "1.ADD	2.SUB	3.MUL	4.DIV	5.EXP" << endl;
		cout << "6.SEND	7.RECV	8.SKIP	9.EXIT" << endl;
        
		cin >> op;

		if (op == 8)
			continue;
		if (op == 9)
			break;

		compute(op, arr, size, sub);
	}
	return 0;
}

int main() {

	//创建内部飞地
	int num;
	cout << "Please enter the number of subEnclaves: ";
	cin >> num;
	subEnclave List[num];

	//设置内部飞地ID
	Set_subEnclaveID(List, num);

	//使用内部飞地
	Use_subEnclave(List, num);
	return 0;
}